/*
 * Copyright (c) 2022 Hong Jiahua
 * https://gitee.com/arrco/ekvdb
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "ekvdb.h"
/************************************************************************/
/*                                                                      */
/************************************************************************/
void ekvdb_write_read_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    int readval;
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_delete_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    int readval;
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //删除数据
    for(int i = 0; i < 8; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_delete(EKVDB_TEST_PATH, name);
        printf("delete i %d key %s\n", i, name);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_compact_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //打印冗余量
    printf("%d\n\n", ekvdb_redundant(EKVDB_TEST_PATH));
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i + 30);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    int readval;
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //打印冗余量
    printf("%d\n\n", ekvdb_redundant(EKVDB_TEST_PATH));
    
    //清除冗余
    ekvdb_compact(EKVDB_TEST_PATH);
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //打印冗余量
    printf("%d\n\n", ekvdb_redundant(EKVDB_TEST_PATH));
   
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_extend_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    int readval;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //打印容量
    printf("%d\n\n", ekvdb_capacity(EKVDB_TEST_PATH));
    
    //扩展容量
    ret = ekvdb_extend(EKVDB_TEST_PATH);
    if(ret < 0)
        printf("extend fail ret %d\n", ret);
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //写数据
    for(int i = 16; i < 32; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 32; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //打印容量
    printf("%d\n\n", ekvdb_capacity(EKVDB_TEST_PATH));
    
    //扩展容量
    ret = ekvdb_extend(EKVDB_TEST_PATH);
    if(ret < 0)
        printf("extend fail ret %d\n", ret);
    
    //读数据
    for(int i = 0; i < 32; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //打印容量
    printf("%d\n\n", ekvdb_capacity(EKVDB_TEST_PATH));
   
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_auto_extend_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    int readval;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //打印容量
    printf("%d\n\n", ekvdb_capacity(EKVDB_TEST_PATH));
    
    //写数据
    for(int i = 16; i < 64; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 64; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
        else
            printf("read fail i %d key %s\n", i, name);
    }
    printf("\n");
    
    //打印容量
    printf("%d\n\n", ekvdb_capacity(EKVDB_TEST_PATH));
   
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_auto_compact_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    int readval;
    
    //创建数据库，设置自动清除冗余阈值123Byte
    ekvdb_create(EKVDB_TEST_PATH, 16, 123);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //打印冗余量
    printf("%d\n\n", ekvdb_redundant(EKVDB_TEST_PATH));
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i + 30);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //打印冗余量
    printf("%d\n\n", ekvdb_redundant(EKVDB_TEST_PATH));
    
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_count_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    int readval;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i + 30);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //打印数据数量
    printf("%d\n\n", ekvdb_count(EKVDB_TEST_PATH));
    
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_reset_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    int readval;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i + 30);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //打印数据数量
    printf("%d\n\n", ekvdb_count(EKVDB_TEST_PATH));
    
    ekvdb_reset(EKVDB_TEST_PATH);
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        if(ret >= 0)
            printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    //打印数据数量
    printf("%d\n\n", ekvdb_count(EKVDB_TEST_PATH));
    
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

void ekvdb_iterator_test(void)
{
#define EKVDB_TEST_PATH     "./"
    
    char name[128];
    int ret;
    int readval;
    
    //创建数据库
    ekvdb_create(EKVDB_TEST_PATH, 16, 0);
    
    //写数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        printf("write i %d key %s val %d\n", i, name, i + 30);
        ret = ekvdb_write(EKVDB_TEST_PATH, name, &i, sizeof(int));
        if(ret <= 0)
            printf("ret %d %d\n", ret, i);
    }
    printf("\n");
    
    //读数据
    for(int i = 0; i < 16; i++) {
        sprintf(name, "%d%d", i, i);
        readval = 6666;
        ret = ekvdb_read(EKVDB_TEST_PATH, name, &readval, sizeof(int));
        printf("read i %d key %s val %d\n", i, name, readval);
    }
    printf("\n");
    
    char keybuf[16];
    ekvdb_iterator_t iterator;
    ekvdb_iterator_init(EKVDB_TEST_PATH, &iterator);
    while(1) {
        ret = ekvdb_iterator_next(EKVDB_TEST_PATH, &iterator, keybuf, sizeof(keybuf), &readval, sizeof(readval));
        if(ret < 0)
            break;
        printf("keybuf %s\n", keybuf);
        printf("readval %d\n", readval);
    }
    
    //清空删除数据库
    ekvdb_clear(EKVDB_TEST_PATH);
}

int main(int argc, char* argv[])
{
    // 读写测试
    ekvdb_write_read_test();
    
    // 删除测试
    // ekvdb_delete_test();
    
    // 清除冗余数据测试
    // ekvdb_compact_test();
    
    // 扩展容量测试
    // ekvdb_extend_test();
    
    // 自动扩展容量测试
    // ekvdb_auto_extend_test();
    
    // 自动清除冗余数据测试
    // ekvdb_auto_compact_test();
    
    // 数据计数测试
    // ekvdb_count_test();
    
    // 重置测试
    // ekvdb_reset_test();
    
    // 数据迭代测试
    // ekvdb_iterator_test();
    
    return 0;
}